const rp = require('request-promise')
const stream = require('stream')
const crypto = require('crypto')
const request = require('base')
const synctool = require('synctool')
const apiObj = require('api')

// 获取图片的宽高
function getImageWH(buffer) {
	try {
		// 检查 PNG 签名
		if (buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4E && 
			buffer[3] === 0x47 && buffer[4] === 0x0D && buffer[5] === 0x0A && 
			buffer[6] === 0x1A && buffer[7] === 0x0A) {
			// PNG 格式：宽度在 16-19 字节，高度在 20-23 字节
			return {
				width: buffer.readUInt32BE(16),
				height: buffer.readUInt32BE(20)
			};
		}
    
		// 检查 JPG 签名
		if (buffer[0] === 0xFF && buffer[1] === 0xD8) {
			// JPG 格式解析（简化版）
			let offset = 2;
			while (offset < buffer.length) {
				if (buffer[offset] === 0xFF && buffer[offset + 1] === 0xC0) {
					return {
						height: buffer.readUInt16BE(offset + 5),
						width: buffer.readUInt16BE(offset + 7)
					};
				}
				offset += 1;
			}
		}
		return {}; // 未知格式
	} catch (error) {
		console.error('Failed to parse image dimensions:', error);
		return {};
	}
}

/**
 * 要求改云服务空间有file数据库
 * 前端使用图片跨域等原因无法上传的图片，通过后端上传至云存储
 * @param {string} url 图片URL
 */
exports.main = async (event, context) => {
	request.handleBefore({event, context})
	const {current}  = request.basedata
	const tableInfo = {
		space: current,
		name: request.basedata[current].fileDb,
		// 是否使用七牛云存储。在后端还需要本云服务空间开通才算，前端则可以跨云服务空间
		qiniu: apiObj.qiniu && apiObj.qiniu.getUploadFileOptions && (!apiObj.qiniu.getUploadFileOptions.space || apiObj.qiniu.getUploadFileOptions.space === current),
	}
	// 接收网络图片URL
	var {
		url,
		fileMediatype = 'image', // 指定的文件类型。默认是图片
		name,  // 文件名。不含后缀
		used = 0, // 文件用途 0：默认；1：素材
		source = 'ai', // default：本地上传；copy：网络粘贴；ai：AI作图
		space = request.basedata.current, // 当前云服务空间
		target = [request.common.necessary.Target],
		partya = [request.common.necessary.Partya],
	} = event
	if (!url) {
		return {
			errCode: 'URL_IS_NULL',
			errMsg: '缺少图片URL参数'
		}
	}
	return new Promise((resolve, reject) => {
		rp({
			uri: url,
			encoding: null,
			resolveWithFullResponse: true
		}).then(response => {
			const success = (data, message) => {
				resolve(request.getResult({data, message}))
			}
			// 检查响应状态码
			if (response.statusCode === 200) {
				// 获取文件MD5值
				const md5 = crypto.createHash('md5').update(response.body).digest('hex')
				// 查询该文件是否已存在
				request.get({...tableInfo, where: {md5}}).then(async (res) => {
					// 如果文件已存在，则直接返回文件信息
					if (res.data.length > 0) {
						return success(res.data[0], '已上传，获取信息成功')
					}
					// 获取该图片的mime
					const mime = response.headers['content-type']
					// 文件名后缀
					const extension = mime.split('/').pop() || url.split('.').pop().split('?')[0] || ''
					const cloudPath = `${md5}-${space}-${fileMediatype}${extension ? ('.' + extension) : ''}`
					if (!name) { // 如果未指定文件名，则使用cloudPath，但是不能有后缀名
						name = cloudPath.split('.')[0]
					}
					// 获取图片宽高值
					const {width, height} = fileMediatype === 'image' ? await getImageWH(response.body) : {}
					const scale = synctool.number.round(width / height)
					// 时长。音频视频特有
					const duration = undefined
					// 获取该文件的大小
					const size = response.headers['content-length']
					// 生成唯一文件名
					const fileName = `ai/${name}.${extension}`
					const fileData = {
						md5, // MD5值
						url: '', // 最终的文件链接
						source, // 来源。default：本地上传；copy：网络粘贴；ai：AI作图
						original: url, // 文件的原始链接
						fileType: mime, // 实际的文件类型
						type: fileMediatype, // 文件类型。同fileMediatype
						used, // 文件用途 0：默认；1：素材
						name, // 文件名。不含后缀
						extension, // 文件名后缀
						size: response.headers['content-length'], // 文件大小。单位b
						width, // 文件宽度。图片视频特有
						height, // 文件高度。图片视频特有
						scale, // 宽高比例。图片视频特有
						duration, // 时长。音频视频特有
						/**
						 * 存储于云的名称
						 * 名称(md5)-云服务空间名-文件类型。后缀名(如果没有后缀名，就没有.)
						 * 云服务空间名：是为了通过url判断向哪个云服务空间获取文件信息
						 * 文件类型：是为了通过url判断文件显示的类型
						 * 后缀名：是为了通过url判断文件真实类型
						 * 
						 * 腾讯云cloudPath不能重复，否则覆盖。如果没有权限则上传失败
						 * 目前已知阿里云中，返回的url看起来和cloudPath并没有关系
						 */
						cloudPath,
						target, partya,
					}
					var uploadParams = {
							cloudPath: fileName,
							fileContent: response.body,
						}
					if (tableInfo.qiniu) { // 上传至七牛云存储。当前未验证！
						const qiniu = uniCloud.importObject('qiniu')
						var res = await qiniu.getUploadFileOptions(fileData)
						uploadParams = {
							...res.data.uploadFileOptions,
							...uploadParams
						}
					}
					// 上传请求
					uniCloud.uploadFile(uploadParams).then(uploadResult => {
						// 处理上传结果
						synctool.handleUploadResult(fileData, uploadResult, res.data)
						// 写入数据库
						request.add({...tableInfo, data: fileData, isReturn: true}).then(res => {
							success(res.data[0], '图片上传成功')
						}).catch(reject)
					}).catch(reject)
				}).catch(reject) 
			} else {
				reject(request.getError('图片请求失败', response.statusCode))
			}
		}).catch(reject)
	})
}